package logic

import (
	mysqldao "ahutoj/web/dao/mysqlDao"
	"ahutoj/web/io/constanct"
	"ahutoj/web/io/request"
	"ahutoj/web/io/response"
	"ahutoj/web/utils"

	"fmt"
	"os/exec"

	"github.com/gin-gonic/gin"
)

func Sim(ctx *gin.Context, req *request.SimReq) (interface{}, error) {
	logger := utils.GetLogInstance()
	submits, err := mysqldao.SelectSubmitsBySIDs(ctx, req.OtherSIDs)
	data := make([]response.SimItem, len(submits))
	if err != nil {
		logger.Errorf("SelectSubmitsBySIDs error:%v", err)
		return nil, err
	}
	savePath := "/sim"
	scriptPath := "./bin" + "/" + getSuffixByLANG(req.LANG)
	submit, err := mysqldao.SelectSubmitBySID(ctx, req.SID)
	if err != nil {
		logger.Errorf("SelectSubmitBySID error:%v", err)
		return nil, err
	}
	utils.SaveFile(savePath, "main.cpp", []byte(submit.Source))
	for index, submit := range submits {
		filename := fmt.Sprintf("%d.cpp", index)
		err = utils.SaveFile(savePath, filename, []byte(submit.Source))
		if err != nil {
			logger.Errorf("SaveFile error:%v", err)
			return nil, err
		}
		output, err := runSimCommand(scriptPath, savePath+"/"+"main.cpp", savePath+"/"+filename)
		logger.Debugf("runSimCommand output:%s", output)
		if err != nil {
			logger.Errorf("runSimCommand error:%v", err)
			return nil, err
		}
		data[index].Similarity = output
		data[index].SID = submit.SID
	}
	err = utils.DeleteFilesDir(savePath)
	if err != nil {
		logger.Errorf("DeleteFilesDir error:%v", err)
		return nil, err
	}
	return response.SimResp{
		Response: response.CreateResponse(constanct.SuccessCode),
		Data:     &data,
	}, nil
}

func runSimCommand(scriptPath, one, other string) (string, error) {
	logger := utils.GetLogInstance()
	ok, err := utils.CheckPathExists(scriptPath)
	if err != nil {
		logger.Errorf("CheckPathExists error:%v", err)
		return "", err
	}
	if !ok {
		logger.Errorf("script file not exists:%s", scriptPath)
		return "", fmt.Errorf("script file not exists:%s", scriptPath)
	}
	cmd := exec.Command(scriptPath,"-p", one, other)
	output, err := cmd.CombinedOutput()
	if err != nil {
		logger.Errorf("command failed: %v, output: %s", err, output)
		return "", err
	}
	return string(output), nil
}

func getSuffixByLANG(lang constanct.LANG) string {
	base := "sim_"
	suffix := ""
	switch lang {
	case constanct.C:
		suffix = "c"
	case constanct.CPP17:
		suffix = "c++"
	case constanct.JAVA:
		suffix = "java"
	}
	return base + suffix
}
